<template>
  <div class="admin-container">
    <!-- 页面标题与操作区 -->
    <div class="page-header">
      <h2>工人-果树管理</h2>
      <div class="operation-btns">
        <button class="btn primary" @click="openAddDialog">新增基准值</button>
        <button
          class="btn danger"
          @click="batchDeleteTrees"
          :disabled="selectedTypes.length === 0"
        >
          批量删除
        </button>
      </div>
    </div>

    <!-- 搜索区 -->
    <div class="search-bar">
      <input
        type="text"
        v-model="searchType"
        placeholder="输入果树类型搜索"
        class="search-input"
      />
      <button class="btn primary" @click="fetchTreeList">搜索</button>
      <button class="btn default" @click="resetSearch">重置</button>
    </div>

    <!-- 果树基准值列表 -->
    <div class="table-container">
      <table class="data-table">
        <thead>
          <tr>
            <th class="select-col">
              <input
                type="checkbox"
                @change="selectAll"
                v-model="allSelected"
              />
            </th>
            <th>果树编号</th>
            <th>最低温度(℃)</th>
            <th>最高温度(℃)</th>
            <th>最低土壤湿度</th>
            <th>最高土壤湿度</th>
            <th>最低降雨量</th>
            <th>最高降雨量</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="tree in treeList" :key="tree.type">
            <td>
              <input
                type="checkbox"
                v-model="selectedTypes"
                :value="tree.type"
                @change="checkAllSelected"
              />
            </td>
            <td>{{ tree.type }}</td>
            <td>{{ tree.minTemp || "-" }}</td>
            <td>{{ tree.maxTemp || "-" }}</td>
            <td>{{ tree.minSoilM || "-" }}</td>
            <td>{{ tree.maxSoilM || "-" }}</td>
            <td>{{ tree.minRaindrops || "-" }}</td>
            <td>{{ tree.maxRaindrops || "-" }}</td>
            <td class="operation-col">
              <button class="btn text" @click="openEditDialog(tree)">
                编辑
              </button>
              <button class="btn text danger" @click="deleteTree(tree.type)">
                删除
              </button>
            </td>
          </tr>
          <tr v-if="treeList.length === 0">
            <td colspan="9" class="empty-state">暂无数据</td>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- 新增果树基准值弹窗 -->
    <div class="modal-mask" v-if="addDialogVisible">
      <div class="modal">
        <div class="modal-header">
          <h3>新增果树基准值</h3>
          <button class="close-btn" @click="addDialogVisible = false">
            &times;
          </button>
        </div>
        <div class="modal-body">
          <form @submit.prevent="submitAddForm" class="modal-form">
            <div class="form-group">
              <label>果树类型 <span class="required">*</span></label>
              <input
                type="text"
                v-model="addForm.type"
                @input="validateType(addForm.type, 'add')"
                @blur="validateType(addForm.type, 'add')"
              />
              <p v-if="addErrors.type" class="error-message">
                {{ addErrors.type }}
              </p>
            </div>
            <div class="form-group">
              <label>最低温度(℃) <span class="required">*</span></label>
              <input
                type="number"
                step="0.1"
                v-model="addForm.minTemp"
                @input="validateNumber(addForm.minTemp, 'minTemp', 'add')"
                @blur="validateNumber(addForm.minTemp, 'minTemp', 'add')"
              />
              <p v-if="addErrors.minTemp" class="error-message">
                {{ addErrors.minTemp }}
              </p>
            </div>
            <div class="form-group">
              <label>最高温度(℃) <span class="required">*</span></label>
              <input
                type="number"
                step="0.1"
                v-model="addForm.maxTemp"
                @input="validateTempRange('add')"
                @blur="validateTempRange('add')"
              />
              <p v-if="addErrors.maxTemp" class="error-message">
                {{ addErrors.maxTemp }}
              </p>
            </div>
            <div class="form-group">
              <label>最低土壤湿度 <span class="required">*</span></label>
              <input
                type="number"
                v-model="addForm.minSoilM"
                @input="validateNumber(addForm.minSoilM, 'minSoilM', 'add')"
                @blur="validateNumber(addForm.minSoilM, 'minSoilM', 'add')"
              />
              <p v-if="addErrors.minSoilM" class="error-message">
                {{ addErrors.minSoilM }}
              </p>
            </div>
            <div class="form-group">
              <label>最高土壤湿度 <span class="required">*</span></label>
              <input
                type="number"
                v-model="addForm.maxSoilM"
                @input="validateSoilMRange('add')"
                @blur="validateSoilMRange('add')"
              />
              <p v-if="addErrors.maxSoilM" class="error-message">
                {{ addErrors.maxSoilM }}
              </p>
            </div>
            <div class="form-group">
              <label>最低降雨量 <span class="required">*</span></label>
              <input
                type="number"
                v-model="addForm.minRaindrops"
                @input="
                  validateNumber(addForm.minRaindrops, 'minRaindrops', 'add')
                "
                @blur="
                  validateNumber(addForm.minRaindrops, 'minRaindrops', 'add')
                "
              />
              <p v-if="addErrors.minRaindrops" class="error-message">
                {{ addErrors.minRaindrops }}
              </p>
            </div>
            <div class="form-group">
              <label>最高降雨量 <span class="required">*</span></label>
              <input
                type="number"
                v-model="addForm.maxRaindrops"
                @input="validateRaindropsRange('add')"
                @blur="validateRaindropsRange('add')"
              />
              <p v-if="addErrors.maxRaindrops" class="error-message">
                {{ addErrors.maxRaindrops }}
              </p>
            </div>
            <div class="form-actions">
              <button
                type="button"
                class="btn default"
                @click="addDialogVisible = false"
              >
                取消
              </button>
              <button
                type="submit"
                class="btn primary"
                :disabled="!isAddFormValid"
              >
                确定
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- 编辑果树基准值弹窗 -->
    <div class="modal-mask" v-if="editDialogVisible">
      <div class="modal">
        <div class="modal-header">
          <h3>编辑果树</h3>
          <button class="close-btn" @click="editDialogVisible = false">
            &times;
          </button>
        </div>
        <div class="modal-body">
          <form @submit.prevent="submitEditForm" class="modal-form">
            <div class="form-group">
              <label>果树编号 <span class="required">*</span></label>
              <input
                type="text"
                v-model="editForm.type"
                @input="validateType(editForm.type, 'edit')"
                @blur="validateType(editForm.type, 'edit')"
                :readonly="true"
              />
              <p v-if="editErrors.type" class="error-message">
                {{ editErrors.type }}
              </p>
            </div>
            <div class="form-group">
              <label>最低温度(℃)</label>
              <input
                type="number"
                step="0.1"
                v-model="editForm.minTemp"
                @input="validateNumber(editForm.minTemp, 'minTemp', 'edit')"
                @blur="validateNumber(editForm.minTemp, 'minTemp', 'edit')"
              />
              <p v-if="editErrors.minTemp" class="error-message">
                {{ editErrors.minTemp }}
              </p>
            </div>
            <div class="form-group">
              <label>最高温度(℃)</label>
              <input
                type="number"
                step="0.1"
                v-model="editForm.maxTemp"
                @input="validateTempRange('edit')"
                @blur="validateTempRange('edit')"
              />
              <p v-if="editErrors.maxTemp" class="error-message">
                {{ editErrors.maxTemp }}
              </p>
            </div>
            <div class="form-group">
              <label>最低土壤湿度</label>
              <input
                type="number"
                v-model="editForm.minSoilM"
                @input="validateNumber(editForm.minSoilM, 'minSoilM', 'edit')"
                @blur="validateNumber(editForm.minSoilM, 'minSoilM', 'edit')"
              />
              <p v-if="editErrors.minSoilM" class="error-message">
                {{ editErrors.minSoilM }}
              </p>
            </div>
            <div class="form-group">
              <label>最高土壤湿度</label>
              <input
                type="number"
                v-model="editForm.maxSoilM"
                @input="validateSoilMRange('edit')"
                @blur="validateSoilMRange('edit')"
              />
              <p v-if="editErrors.maxSoilM" class="error-message">
                {{ editErrors.maxSoilM }}
              </p>
            </div>
            <div class="form-group">
              <label>最低降雨量</label>
              <input
                type="number"
                v-model="editForm.minRaindrops"
                @input="
                  validateNumber(editForm.minRaindrops, 'minRaindrops', 'edit')
                "
                @blur="
                  validateNumber(editForm.minRaindrops, 'minRaindrops', 'edit')
                "
              />
              <p v-if="editErrors.minRaindrops" class="error-message">
                {{ editErrors.minRaindrops }}
              </p>
            </div>
            <div class="form-group">
              <label>最高降雨量</label>
              <input
                type="number"
                v-model="editForm.maxRaindrops"
                @input="validateRaindropsRange('edit')"
                @blur="validateRaindropsRange('edit')"
              />
              <p v-if="editErrors.maxRaindrops" class="error-message">
                {{ editErrors.maxRaindrops }}
              </p>
            </div>
            <div class="form-actions">
              <button
                type="button"
                class="btn default"
                @click="editDialogVisible = false"
              >
                取消
              </button>
              <button
                type="submit"
                class="btn primary"
                :disabled="!isEditFormValid"
              >
                确定
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- 提示消息 -->
    <div class="toast" v-if="toastMessage">{{ toastMessage }}</div>
  </div>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from "vue";
import axios from "axios";
import { inMemoryStorage } from "/src/router/index.js";
import { useRouter } from "vue-router";

// 初始化路由实例
const router = useRouter();

// axios 核心配置
axios.defaults.baseURL = "http://localhost:8080";
axios.defaults.withCredentials = true;
axios.defaults.headers.common["Accept"] = "application/json";
axios.defaults.headers.post["Content-Type"] = "application/json;charset=UTF-8";

// 请求拦截器
axios.interceptors.request.use(
  (config) => {
    const token = inMemoryStorage.token || "";
    if (token) {
      config.headers["Authorization"] = `Bearer ${token}`;
    }
    if (!token && !config.url.includes("/login")) {
      router.replace("/");
      showToast("请先登录");
      return Promise.reject(new Error("未登录"));
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
axios.interceptors.response.use(
  (response) => {
    if (response.data?.message) {
      showToast(response.data.message);
    } else if (typeof response.data === "string") {
      showToast(response.data);
    }
    return response;
  },
  (error) => {
    if (error.response) {
      const status = error.response.status;
      const message = error.response.data?.message || "操作失败";
      showToast(`[${status}] ${message}`);
      if (status === 401) {
        inMemoryStorage.token = null;
        router.replace("/");
        showToast("登录已失效，请重新登录");
      }
    } else if (error.request) {
      showToast("无法连接服务器，请检查后端是否启动");
    } else {
      showToast("请求异常：" + error.message);
    }
    return Promise.reject(error);
  }
);

// 数据列表
const allTrees = ref([]);
const treeList = ref([]);
const searchType = ref("");

// 选择相关
const selectedTypes = ref([]);
const allSelected = ref(false);

// 弹窗控制
const addDialogVisible = ref(false);
const editDialogVisible = ref(false);

// 表单数据（与后端TreeReferenceDTO字段对应）
const addForm = reactive({
  type: "",
  minTemp: "",
  maxTemp: "",
  minSoilM: "",
  maxSoilM: "",
  minRaindrops: "",
  maxRaindrops: "",
});

const editForm = reactive({
  type: "",
  minTemp: "",
  maxTemp: "",
  minSoilM: "",
  maxSoilM: "",
  minRaindrops: "",
  maxRaindrops: "",
});

// 错误信息
const addErrors = reactive({
  type: "",
  minTemp: "",
  maxTemp: "",
  minSoilM: "",
  maxSoilM: "",
  minRaindrops: "",
  maxRaindrops: "",
});

const editErrors = reactive({
  type: "",
  minTemp: "",
  maxTemp: "",
  minSoilM: "",
  maxSoilM: "",
  minRaindrops: "",
  maxRaindrops: "",
});

const toastMessage = ref("");

// 表单验证状态
const isAddFormValid = computed(() => {
  return (
    !addErrors.type &&
    !addErrors.minTemp &&
    !addErrors.maxTemp &&
    !addErrors.minSoilM &&
    !addErrors.maxSoilM &&
    !addErrors.minRaindrops &&
    !addErrors.maxRaindrops &&
    addForm.type.trim() &&
    addForm.minTemp !== "" &&
    addForm.maxTemp !== "" &&
    addForm.minSoilM !== "" &&
    addForm.maxSoilM !== "" &&
    addForm.minRaindrops !== "" &&
    addForm.maxRaindrops !== ""
  );
});

const isEditFormValid = computed(() => {
  return (
    !editErrors.type &&
    !editErrors.minTemp &&
    !editErrors.maxTemp &&
    !editErrors.minSoilM &&
    !editErrors.maxSoilM &&
    !editErrors.minRaindrops &&
    !editErrors.maxRaindrops &&
    editForm.type.trim()
  );
});

// 加载果树基准值列表
const fetchAllTrees = async () => {
  try {
    const response = await axios.post("/device/operate/selectTreeReference");
    allTrees.value = response.data || [];
    filterTreesByType();
  } catch (error) {
    console.error("获取果树基准值列表失败:", error);
    showToast("获取数据失败，请重试");
  }
};

// 前端按果树类型过滤
const filterTreesByType = () => {
  const typeStr = searchType.value.trim();
  if (!typeStr) {
    treeList.value = [...allTrees.value];
    return;
  }
  const filtered = allTrees.value.filter((tree) => tree.type.includes(typeStr));
  treeList.value = filtered;
};

// 搜索触发
const fetchTreeList = async () => {
  await fetchAllTrees();
};

// 页面加载时初始化
onMounted(() => {
  fetchTreeList();
});

// 提示消息
const showToast = (message) => {
  toastMessage.value = message;
  setTimeout(() => {
    toastMessage.value = "";
  }, 3000);
};

// 全选/取消全选
const selectAll = () => {
  if (allSelected.value) {
    selectedTypes.value = treeList.value.map((tree) => tree.type);
  } else {
    selectedTypes.value = [];
  }
};

// 检查全选状态
const checkAllSelected = () => {
  allSelected.value =
    treeList.value.length > 0 &&
    selectedTypes.value.length === treeList.value.length;
};

// 重置搜索
const resetSearch = () => {
  searchType.value = "";
  fetchTreeList();
};

// 验证果树类型
const validateType = (value, type) => {
  const errors = type === "add" ? addErrors : editErrors;
  const typeStr = value.trim();
  if (!typeStr) {
    errors.type = "果树类型不能为空";
  } else if (typeStr.length > 50) {
    errors.type = "果树类型长度不能超过50个字符";
  } else {
    if (
      type === "add" &&
      allTrees.value.some((tree) => tree.type === typeStr)
    ) {
      errors.type = "该果树类型已存在";
    } else {
      errors.type = "";
    }
  }
};

// 验证数字输入
const validateNumber = (value, key, type) => {
  const errors = type === "add" ? addErrors : editErrors;
  if (value === "" && type === "edit") {
    errors[key] = ""; // 编辑时可为空
    return;
  }
  if (value === "" && type === "add") {
    if (key.includes("Temp")) errors[key] = "温度不能为空";
    else if (key.includes("SoilM")) errors[key] = "土壤湿度不能为空";
    else if (key.includes("Raindrops")) errors[key] = "降雨量不能为空";
    return;
  }
  const num = Number(value);
  if (isNaN(num) || num < 0) {
    errors[key] = "必须为非负数字";
  } else {
    errors[key] = "";
  }
};

// 验证温度范围（最高>最低）
const validateTempRange = (type) => {
  const form = type === "add" ? addForm : editForm;
  const errors = type === "add" ? addErrors : editErrors;

  if (form.minTemp === "" || form.maxTemp === "") return;

  const min = Number(form.minTemp);
  const max = Number(form.maxTemp);

  if (!isNaN(min) && !isNaN(max) && max <= min) {
    errors.maxTemp = "最高温度必须大于最低温度";
  } else {
    errors.maxTemp = "";
  }
};

// 验证土壤湿度范围（最高>最低）
const validateSoilMRange = (type) => {
  const form = type === "add" ? addForm : editForm;
  const errors = type === "add" ? addErrors : editErrors;

  if (form.minSoilM === "" || form.maxSoilM === "") return;

  const min = Number(form.minSoilM);
  const max = Number(form.maxSoilM);

  if (!isNaN(min) && !isNaN(max) && max <= min) {
    errors.maxSoilM = "最高土壤湿度必须大于最低土壤湿度";
  } else {
    errors.maxSoilM = "";
  }
};

// 验证降雨量范围（最高>最低）
const validateRaindropsRange = (type) => {
  const form = type === "add" ? addForm : editForm;
  const errors = type === "add" ? addErrors : editErrors;

  if (form.minRaindrops === "" || form.maxRaindrops === "") return;

  const min = Number(form.minRaindrops);
  const max = Number(form.maxRaindrops);

  if (!isNaN(min) && !isNaN(max) && max <= min) {
    errors.maxRaindrops = "最高降雨量必须大于最低降雨量";
  } else {
    errors.maxRaindrops = "";
  }
};

// 打开新增弹窗
const openAddDialog = () => {
  Object.keys(addForm).forEach((key) => (addForm[key] = ""));
  Object.keys(addErrors).forEach((key) => (addErrors[key] = ""));
  addDialogVisible.value = true;
};

// 提交新增表单
const submitAddForm = async () => {
  try {
    const payload = {
      type: addForm.type.trim(),
      minTemp: Number(addForm.minTemp),
      maxTemp: Number(addForm.maxTemp),
      minSoilM: Number(addForm.minSoilM),
      maxSoilM: Number(addForm.maxSoilM),
      minRaindrops: Number(addForm.minRaindrops),
      maxRaindrops: Number(addForm.maxRaindrops),
    };
    await axios.post("/device/operate/addTreeReference", payload);
    addDialogVisible.value = false;
    await fetchTreeList();
  } catch (error) {
    console.error("新增失败:", error);
    showToast("新增失败，请重试");
  }
};

// 打开编辑弹窗
const openEditDialog = (tree) => {
  editForm.type = tree.type;
  editForm.minTemp = tree.minTemp || "";
  editForm.maxTemp = tree.maxTemp || "";
  editForm.minSoilM = tree.minSoilM || "";
  editForm.maxSoilM = tree.maxSoilM || "";
  editForm.minRaindrops = tree.minRaindrops || "";
  editForm.maxRaindrops = tree.maxRaindrops || "";
  Object.keys(editErrors).forEach((key) => (editErrors[key] = ""));
  editDialogVisible.value = true;
};

// 提交编辑表单
const submitEditForm = async () => {
  try {
    const updateData = {
      type: editForm.type.trim(),
      ...(editForm.minTemp !== "" && { minTemp: Number(editForm.minTemp) }),
      ...(editForm.maxTemp !== "" && { maxTemp: Number(editForm.maxTemp) }),
      ...(editForm.minSoilM !== "" && { minSoilM: Number(editForm.minSoilM) }),
      ...(editForm.maxSoilM !== "" && { maxSoilM: Number(editForm.maxSoilM) }),
      ...(editForm.minRaindrops !== "" && {
        minRaindrops: Number(editForm.minRaindrops),
      }),
      ...(editForm.maxRaindrops !== "" && {
        maxRaindrops: Number(editForm.maxRaindrops),
      }),
    };
    await axios.post("/device/operate/updateTreeReference", updateData);
    editDialogVisible.value = false;
    await fetchTreeList();
  } catch (error) {
    console.error("编辑失败:", error);
    showToast("编辑失败，请重试");
  }
};

// 单个删除
const deleteTree = async (type) => {
  if (!confirm(`确定要删除 ${type} 的基准值吗？`)) return;

  try {
    await axios.post(
      "/device/operate/deleteTreeReference",
      {},
      {
        params: { type },
      }
    );
    await fetchTreeList();
    selectedTypes.value = selectedTypes.value.filter((t) => t !== type);
    checkAllSelected();
  } catch (error) {
    console.error("删除失败:", error);
    showToast("删除失败，请重试");
  }
};

// 批量删除
const batchDeleteTrees = async () => {
  if (!confirm(`确定要删除选中的 ${selectedTypes.value.length} 条基准值吗？`))
    return;

  try {
    for (const type of selectedTypes.value) {
      await axios.post(
        "/device/operate/deleteTreeReference",
        {},
        {
          params: { type },
        }
      );
    }
    showToast("批量删除成功");
    selectedTypes.value = [];
    allSelected.value = false;
    await fetchTreeList();
  } catch (error) {
    console.error("批量删除失败:", error);
    showToast("批量删除失败，请重试");
  }
};
</script>
<style scoped>
.admin-container {
  padding: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

.operation-btns {
  display: flex;
  gap: 10px;
}

.search-bar {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
  align-items: center;
}

.search-input {
  flex: 0 0 300px;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.table-container {
  overflow-x: auto;
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid #eee;
}

.data-table th,
.data-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #eee;
}

.data-table th {
  background-color: #f9f9f9;
  font-weight: 600;
}

.select-col {
  width: 50px;
}

.operation-col {
  display: flex;
  gap: 10px;
}

.empty-state {
  text-align: center;
  padding: 40px;
  color: #999;
}

.modal-mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal {
  background-color: white;
  border-radius: 6px;
  width: 100%;
  max-width: 500px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.modal-header {
  padding: 15px 20px;
  border-bottom: 1px solid #eee;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.modal-body {
  padding: 20px;
}

.modal-form {
  display: flex;
  flex-direction: column;
  gap: 15px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.form-group label {
  font-weight: 500;
  color: #333;
}

.form-group input,
.form-group textarea {
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.form-group textarea {
  resize: vertical;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 10px;
}

.close-btn {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  color: #999;
}

.close-btn:hover {
  color: #333;
}

.error-message {
  color: #f5222d;
  font-size: 12px;
  margin: 0;
}

.toast {
  position: fixed;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 10px 20px;
  border-radius: 4px;
  z-index: 1001;
  animation: fadein 0.3s, fadeout 0.3s 2.7s;
}

.required {
  color: #f5222d;
}

/* 按钮样式 */
.btn {
  padding: 8px 16px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
}

.btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn.primary {
  background-color: #409eff;
  color: white;
}

.btn.primary:hover:not(:disabled) {
  background-color: #66b1ff;
}

.btn.danger {
  background-color: #f5222d;
  color: white;
}

.btn.danger:hover:not(:disabled) {
  background-color: #ff4d4f;
}

.btn.warning {
  background-color: #faad14;
  color: white;
}

.btn.warning:hover:not(:disabled) {
  background-color: #ffc53d;
}

.btn.default {
  background-color: #f5f5f5;
  color: #333;
}

.btn.default:hover:not(:disabled) {
  background-color: #e8e8e8;
}

.btn.text {
  background: none;
  color: #666;
  padding: 4px 8px;
}

.btn.text:hover {
  color: #409eff;
}

.btn.text.primary {
  color: #409eff;
}

.btn.text.danger {
  color: #f5222d;
}

.btn.text.success {
  color: #52c41a;
}

/* 动画效果 */
@keyframes fadein {
  from {
    top: 0;
    opacity: 0;
  }
  to {
    top: 20px;
    opacity: 1;
  }
}

@keyframes fadeout {
  from {
    top: 20px;
    opacity: 1;
  }
  to {
    top: 0;
    opacity: 0;
  }
}

/* 适配小屏幕 */
@media (max-width: 768px) {
  .admin-container {
    padding: 10px;
  }

  .search-input {
    flex: 1;
  }

  .operation-col {
    flex-direction: column;
    gap: 5px;
  }

  .modal {
    width: 90%;
  }
}
</style>
